package main

import (
	"bytes"
	"crypto/sha256"
	"encoding/binary"
	"encoding/gob"
	"log"
	"time"
)

type Block struct {
	// 版本
	Version uint64
	// 前置hash
	PreHash []byte
	// 梅克尔根
	MerkelRoot []byte
	// 时间戳
	TimeStamp uint64
	// 难度系数
	Difficulty uint64
	// 随机数 （挖矿要找的数据）
	Nance uint64

	// 当前hash （正常 比特币中没有当前区块的hash, 我们是为了作比较）
	Hash []byte
	// data
	Data []byte
}

// 创建区块
func NewBlock(data string, preHash []byte) *Block {
	block := Block{
		Version:    00,
		PreHash:    preHash,
		MerkelRoot: []byte{},
		TimeStamp:  uint64(time.Now().Unix()),
		Difficulty: 0,
		Nance:      00,
		Hash:       []byte{},
		Data:       []byte(data),
	}

	//block.SetHash()
	pow := NewProofOfWork(&block)
	hash, nance := pow.Run()
	block.Hash = hash
	block.Nance = nance
	return &block
}

/**
Uint64ToByte
*/
func Uint64ToByte(num uint64) []byte {
	var buffer bytes.Buffer
	err := binary.Write(&buffer, binary.BigEndian, num)
	if err != nil {
		log.Panic(err)
	}
	return buffer.Bytes()
}

// 设置 hash
func (b *Block) SetHash() {
	temp := [][]byte{
		Uint64ToByte(b.Version),
		b.PreHash,
		Uint64ToByte(b.TimeStamp),
		Uint64ToByte(b.Difficulty),
		Uint64ToByte(b.Nance),
		b.Data,
	}
	blockInfo := bytes.Join(temp, []byte{})
	hash := sha256.Sum256(blockInfo)
	b.Hash = hash[:]
}

//序列化
func (block *Block) Serialize() []byte {
	var buffer bytes.Buffer

	//- 使用gob进行序列化（编码）得到字节流
	//1. 定义一个编码器
	//2. 使用编码器进行编码
	encoder := gob.NewEncoder(&buffer)
	err := encoder.Encode(&block)
	if err != nil {
		log.Panic("编码出错!")
	}

	//fmt.Printf("编码后的小明：%v\n", buffer.Bytes())

	return buffer.Bytes()
}

//反序列化
func Deserialize(data []byte) Block {

	decoder := gob.NewDecoder(bytes.NewReader(data))

	var block Block
	//2. 使用解码器进行解码
	err := decoder.Decode(&block)
	if err != nil {
		log.Panic("解码出错!", err)
	}

	return block
}
